<?php
/**
 * UserModel.class.php
 * 微信端用户模型
 *
 * @author  王中艺
 * @date    2016-11-05
 */

namespace Wechat\Model;

class UserModel extends BaseModel{
    
    //重定义数据表明
    protected $trueTableName = 't_user';

    const ROLE_MAP  = [
        106 => 106,
        113 => 102,
        114 => 103,
        115 => 104,
        116 => 105,
        117 => 101
    ];

    /**
     * 添加用户
     * @param array $userInfo 用户信息组
     */
    function addUser($userInfo){
        $isExt  = $this->where('open_id = "%s"', $userInfo['open_id'])->find();
        if($isExt){
            $this->errMsg   = '用户已存在!';
            return false;
        }

        $userInfo['status']     = $userInfo['subscribe'] == 1 ? 1 : 0;
        $userInfo['open_id']    = $userInfo['openid'];
        $userInfo['role_id']    = self::ROLE_MAP[$userInfo['groupid']] ?? 0;
	    if(isset($userInfo['nickname']))
            $userInfo['nickname']       = filter_emoji($userInfo['nickname']);
        if(!isset($userInfo['role_id']))
            $userInfo['role_id']    = 106;
        if(!isset($userInfo['headimgurl']))
            $userInfo['headimgurl'] = 'http://photocdn.sohu.com/20110519/Img280619320.png';

        if(!$userInfo['open_id'])    return false;

        $userId     = $this->add($userInfo);
        return $userId;
    }

    /**
     * 取消关注处理
     * @param   $openId
     * @return  boolean
     */
    function unsubscribe($openId){
        $this->where('open_id = "%s"', $openId)->save(array('status' => 0));
        S('user_info_'.$userId, null);
        return true;
    }

    /**
     * 获取用户角色关系信息
     * @param   $userId
     * @return  $roleInfo
     */
    function getUserRelaInfo($userId){
        $info   = M('t_user_relative', null)
            ->where('user_id = %d', $userId)
            ->find();

        return $info;
    }

    /**
     * 获取用户信息
     * @param   $openId or $userId
     * @return  $userInfo
     */
    function getUserInfo($id){
        if(is_numeric($id)){
            $userInfo   = S('user_info_'.$id);
            if(!$userInfo){
                $userInfo   = $this->where('id = %d', $id)->find();
            }
        }else{
            $userInfo   = $this->where('open_id = "%s"', $id)->find();
        }

        if(!$userInfo) return false;
        //字段定义
        $userInfo['vip_enddate']    = $userInfo['vip_endtime'] ? date('Y-m-d', $userInfo['vip_endtime']) : 0;
        $userInfo['subscribe_date'] = date('Y-m-d', $userInfo['subscribe_time']);
        
        //vip过期时间检测
        if($userInfo['vip_endtime'] < time()){
            $userInfo['vip_level']  = 0;
        }
            
        return $userInfo;
    }

    /**
     * 更新用户信息
     * @param   $userId
     * @param   $userInfo
     * @return  boolean
     */
    function updateUserInfo($userId, $userInfo){
        $userInfo['id']    = $userId;
        
        //字段重定义
        if(isset($userInfo['subscribe']))
            $userInfo['status']     = $userInfo['subscribe'];
        if(isset($userInfo['openid']))
            $userInfo['open_id']    = $userInfo['openid'];
        if(isset($userInfo['groupid'])){
            $userInfo['role_id']    = self::ROLE_MAP[$userInfo['groupid']] ?? 0;
        }
    	if(isset($userInfo['nickname']))
    	    $userInfo['nickname'] 	= filter_emoji($userInfo['nickname']);
        
        $ret    = $this->where('id = %d', $userId)->save($userInfo);
        if($ret === false){
            $this->errMsg   = '信息更改失败!';
            return false;
        }
        S('user_info_'.$userId, null);

        return true;
    }

    /**
     * 注册角色关系信息
     * 以第一次关注为准，之后不变
     * @param   int     $userId
     * @param   array   $relaInfo
     * @return  boolean
     */
    function addUserRelaInfo($userId, $relaInfo){
        $isExt   = M('t_user_relative', null)->where('user_id = '.$userId)->find();
        if($isExt)  return  true;

        $relaInfo['user_id']    = $userId;
        M('t_user_relative', null)->add($relaInfo);

        //关系树上级发展人数增加
        $users  = array();
        $validRelaInfo  = array(
            $relaInfo['dean_id'], 
            $relaInfo['expand_id'], 
            $relaInfo['teacher_id'],
            $relaInfo['parent_id']
        );
        foreach($validRelaInfo as $val){
            if($val > 0 && $val != $userId)    $users[]    = $val;
        }

        $users  = implode(',', $users);
        if($users)
            $this->execute('update t_user set develop_count = develop_count + 1 where id in (%s)', $users);

        //上级家长积分获取
        $parentId   = $relaInfo['parent_id'];
        if($parentId > 0){
            $score  = 10;
            D('Score')->addScore($parentId, 2, $userId, $score);
        }
        return true;
    }

    /**
     * 更改用户角色
     * @param   $openId or $userId
     * @param   $roleId
     * @return  boolean
     */
    function changeUserRole($id, $roleId){
        if(is_numeric($id)){
            $userInfo   = $this->where('id = %d', $id)->find();
        }else{
            $userInfo   = $this->where('open_id = "%s"', $id)->find();
        }
        if(!$userInfo || $userInfo['status'] == 0){
            $this->errMsg   = '用户未找到或用户未关注';
            return false;
        }

        $userId     = $userInfo['id'];
        $openId     = $userInfo['open_id'];
        $oRoleId    = $userInfo['role_id'];
        if($roleId == $oRoleId)
            return true;
        
        $wechat     = \Wechat\Util\WechatExt::getInstance();
        //用户分组请求
        if(!$wechat->updateGroupMembers($roleId, $openId)){
            $this->errMsg   = $wechat->errMsg;
            return false;
        }
        $wxUserInfo     = $wechat->getUserInfo($openId);
      
        //用户信息更改
        if(!$this->updateUserInfo($userId, $wxUserInfo)){
            $this->errMsg   = '数据库更新失败!';
            return false;
        }
        $userInfo['role_id']    = $roleId;
        
        //用户关系链更改
        $relaField  = array(1 => 'dean_id', 2 => 'expand_id', 3 => 'teacher_id', 4 => 'parent_id');
       
        if($oRoleId == 101)     $oRelaId    = 1;    //园长
        else if($oRoleId >= 102 && $oRoleId <=104)   $oRelaId    = 2;    //推销员
        else if($oRoleId == 105) $oRelaId    = 3;    //教师
        else    $oRelaId    = 4;    //家长

        if($roleId == 101)     $relaId    = 1;    //园长
        else if($roleId >= 102 && $roleId <=104)   $relaId    = 2;    //推销员
        else if($roleId == 105) $relaId    = 3;    //教师
        else    $relaId    = 4;    //家长

        if($oRelaId == $relaId)     return true;

        //下线更改
        $this->execute(
            'update t_user_relative set %s = -1 where %s = %d',
            $relaField[$oRelaId],
            $relaField[$oRelaId],
            $userId
        );
       
        //自身更改
        $relaChange[$relaField[$relaId]]   = 0;
        $relaChange[$relaField[$oRelaId]]  = -1;
        if($relaId < $oRelaId-1){
            for($i = $relaId+1; $i < $oRelaId; $i++){
                $relaChange[$relaField[$i]]     = -1;
            }
        }

        M('t_user_relative', null)
            ->where('user_id = %d', $userId)
            ->save($relaChange);
        
        //推送模板消息
        $wxTempMsg  = new \Wechat\Util\WxTempMsg();
        $wxTempMsg->changeRole($openId, $userInfo, $oRoleId);
        //上级消息推送
        $relaInfo   = $this->getUserRelaInfo($userId);
        foreach($relaInfo as $key => $val){
            if($val == 0)   break;
            if($val == -1)  continue;
            if($val != $userId)     $hlId   = $val;
        }
        if($hlId)
            $wxTempMsg->changeRole($hlId, $userInfo, $oRoleId);

        return ture;
    }

    /**
     * 获取用户情景二维码(普通注册)
     * @param   $id
     * @return  $url
     */
    function getQRCode($id, &$uInfo = false){
        if(is_numeric($id)){
            $userInfo   = $this->where('id = %d', $id)->find();
        }else{
            $userInfo   = $this->where('open_id = "%s"', $id)->find();
        }
        
        if($uInfo)
            $uInfo  = $userInfo;
        
        if(!$userInfo || $userInfo['status'] == 0){
            $this->errMsg   = '无效用户ID';
            return false;
        }
        if(!in_array($userInfo['role_id'], array(101, 102, 103, 104, 105,106))){
            $this->errMsg   = '用户角色无效';
            return false;
        }
        $userId     = $userInfo['id'];
        $roleId     = $userInfo['role_id'];

        //判断是否有二维码
        $qrCode     = $userInfo['qrcode'] ? json_decode($userInfo['qrcode'], true) : false;
        if($qrCode && ($qrCode['end_time'] > time() || $qrCode['end_time'] == 0) && $qrCode['norm_link']){
            return $qrCode;
            
        }

        //重新获取二维码
        $wechat     = \Wechat\Util\WechatExt::getInstance();
        $qrCode     = $wechat->getQRCode($userId);
        $codeInfo['norm_url']   = $wechat->getQRUrl($qrCode['ticket']);
        $codeInfo['end_time']   = time() + (int)$qrCode['expire_seconds'] - (3600*24);
        $codeInfo['norm_link']    = $qrCode['url'];

        // if(in_array($userInfo['role_id'], array(105, 106))){
        //     //老师家长二维码获取,临时二维码
        //     $qrCode     = $wechat->getQRCode($userId);
        //     $codeInfo['norm_url']   = $wechat->getQRUrl($qrCode['ticket']);
        //     $codeInfo['end_time']   = time() + (int)$qrCode['expire_seconds'] - (3600*24);
        //     $codeInfo['norm_link']    = $qrCode['url'];
        // }else if(in_array($userInfo['role_id'], array(102, 103, 104))){
        //     //推广员二维码获取，永久二维码
        //     $qrCode     = $wechat->getQRCode($userId, 1);
        //     $codeInfo['norm_url']   = $wechat->getQRUrl($qrCode['ticket']);
        //     $codeInfo['end_time']   = 0;
        //     $codeInfo['norm_link']    = $qrCode['url'];
        // }else{
        //     //院长通用二维码获取
        //     $qrCode     = $wechat->getQRCode($userId, 1);
        //     $codeInfo['norm_url']   = $wechat->getQRUrl($qrCode['ticket']);
        //     $codeInfo['norm_link']  = $qrCode['url'];
        //     // //园长推销员二维码
        //     // $scene  = json_encode(array('cate' => 'sale', 'recom_id' => $userId));
        //     // $saleCode   = $wechat->getQRCode($scene, 2);
        //     // $codeInfo['sale_url']   = $wechat->getQRUrl($saleCode['ticket']);

        //     $codeInfo['end_time'] = 0;
        // }

        $userInfo['qrcode'] = json_encode($codeInfo);
        $this->updateUserInfo($userInfo['id'], $userInfo);

        return $codeInfo;
    }

    /**
     * 获取直属下线用户
     * @param   $userId
     * @param   $type   下线用户类型 1.园长；2.推销员；3.教师；4.家长
     * @param   $page   页码数
     * @param   $count  查询结果数量
     * @return  $list
     */
    function getChildUsers($userInfo, $type, $page, &$count){
        switch($type){
            //园长
            case 1: $where  = 'a.role_id = 101'; break;
            //推销员
            case 2: $where  = 'a.role_id >= 102 and a.role_id <= 104';break;
            //教师
            case 3: $where  = 'a.role_id = 105'; break;
            //家长
            case 4: $where  = 'a.role_id = 106'; break;
        }

        if($userInfo['role_id'] == 101){
            $where  .= ' and b.dean_id = '.$userInfo['id'];
        }else if($userInfo['role_id'] >= 102 && $userInfo['role_id'] <= 104){
            $where  .= ' and b.expand_id = '.$userInfo['id'];
        }else if($userInfo['role_id'] == 105){
            $where  .= ' and b.teacher_id = '.$userInfo['id'];
        }else{
            return false;
        }

        $dUser  = M('t_user a', null);
        $list   = M('t_user a', null)
            ->join('left join t_user_relative b on a.id = b.user_id')
            ->where($where)
            ->page($page, C('PAGE_COUNT'))
            ->cache(true)
            ->select();
        $count  = M('t_user a', null)
            ->join('left join t_user_relative b on a.id = b.user_id')
            ->where($where)
            ->cache(true)
            ->count();
        return $list;
    }

    /**
     * 获取下线用户成绩（目前仅对幸福院长角色开放)
     * @param   $userInfo 用户信息
     * @param   $cRoleId 下线用户角色ID
     * @param   $page 页码数
     * @param   $timeS 开始时间
     * @param   $timeE 结束时间
     * @param   $keyword 关键词
     * @return  array(list)
     */
    function childGpa($userInfo, $cRoleId, $page, $timeS, $timeE, $keyword){
        if($userInfo['role_id'] == 101){
            //幸福院长角色逻辑
            if(in_array($cRoleId, array(102, 103, 104))){
                //下线用户角色为幸福教练
                //查询语句生成
                $where  = sprintf(
                    'a.dean_id=%d and a.expand_id=0 and c.role_id=%d and b.create_time>=%d and b.create_time <= %d',
                    $userInfo['id'], $cRoleId, $timeS, $timeE
                );
                if($keyword)
                    $where  .= sprintf(' and c.nickname like "%%%s%%"', $keyword);

                $list   = M('t_user_relative a', null)
                    ->join('left join t_deduct b on a.user_id = b.user_id')
                    ->join('left join t_user c on a.user_id = c.id')
                    ->group('a.user_id')
                    ->where($where)
                    ->page($page, C('PAGE_COUNT'))
                    // ->cache(true)
                    ->field('sum(b.amount) amount, c.id user_id, c.role_id, c.headimgurl, c.develop_count, c.nickname')
                    ->select();

                return $list;
            }else{
                $this->errMsg   = '无法查询该下线用户角色!';
                return false;
            }
        }else{
            $this->errMsg   = '无法查询角色的下线用户!';
            return false;
        }
    }

    /**
     * 销售(分红)记录获取
     * @param   $userId
     * @param   $page
     * @param   $keywork
     * @return  $list
     */
    function getSoleLog($userId, $page = 1, $keyword){
        $where  = 'a.user_id = '.$userId;
        if($keyword)    $where  .= ' and c.nickname like "%'.$keyword.'%"';

        $list   = M('t_deduct a', null)
            ->join('left join t_money b on a.money_id = b.id')
            ->join('left join t_user c on b.user_id = c.id')
            ->where($where)
            ->order('a.id desc')
            ->page($page, C('PAGE_COUNT'))
            ->cache(true)
            ->field('a.amount, a.percent, a.create_time, b.remark, c.nickname, c.headimgurl')
            ->select();

        foreach($list as &$val){
            $val['remark']  = json_decode($val['remark']);
            $val['create_date'] = date('Y-m-d', $val['create_time']);
        }
        return $list;
    }

    /**
     * 收益详情获取
     * @param $userId   用户ID
     * @param $timeS    起始时间
     * @param $timeE    结束时间
     * @return  $info
     */
    function deductDetail($userId, $timeS, $timeE){
        $list   = M('t_deduct a', null)
            ->join('left join t_user b on a.origin_id = b.id')
            ->where('a.user_id = %d', 
                $userId)
            ->cache(true)
            ->field('a.amount, a.percent, a.origin_id, b.role_id')
            ->select();
        
        $oriDean    = 0;
        $oriExpA    = 0;
        $oriExpB    = 0;
        $oriExpC    = 0;
        $oriTeac    = 0;
        $oriPart    = 0;
        $oriSelf    = 0;
        foreach($list as $val){
            switch($val['role_id']){
                case 101:   $oriDean += $val['amount']; break;
                case 102:   $oriExpA += $val['amount']; break;
                case 103:   $oriExpB += $val['amount']; break;
                case 104:   $oriExpC += $val['amount']; break;
                case 105:   $oriTeac += $val['amount']; break;
                case 106:   $oriPart += $val['amount']; break;
                default:    $oriSelf += $val['amount']; break;
            }
        }

	   $info   = array(
            'ori_dean'  => round($oriDean, 2),
            'ori_exp_a' => round($oriExpA, 2),
            'ori_exp_b' => round($oriExpB, 2),
            'ori_exp_c' => round($oriExpC, 2),
            'ori_teac'  => round($oriTeac, 2),
            'ori_self'  => round($oriSelf, 2),
            'ori_part'  => round($oriPart, 2)
        );
        return $info;
    }

    /**
     * 绑定用户名/手机号
     * @param   $userId
     * @param   $username
     * @param   $childLevel
     * @return  boolean
     */
    function bindUsername($userId, $username, $childLevel){
        $userInfo   = $this->getUserInfo($userId);
        if($userInfo['username']){
            $this->errMsg   = '已绑定过手机号!';
            return false;
        }

        $userInfo['username']   = $username;
        $userInfo['child_level']    = $childLevel;

        $result     = $this->updateUserInfo($userId, $userInfo);
        if($result == false){
            return false;
        }
        
        //绑定成功后赠送会员(试用会员)
        $vipLevel   = $userInfo['vip_level'] ? $userInfo['vip_level'] : 10;
        $timeDesc   = '+5 day';
        $freeGet    = true;
        $this->giveVip($userId, $vipLevel, $timeDesc, $freeGet);

        return true;
    }

    /**
     * 购买VIP
     * @param   $userId
     * @param   $vipId vip种类
     * @param   $couponCode 优惠码
     * @return  $payInfo    支付信息
     */
    function purchaseVip($userId, $vipId, $couponCode = null){
        $vipInfo    = C('VIP_TYPE.'.$vipId);
        if($vipInfo == false){
            $this->errMsg   = 'VIP类型错误!';
            return false;
        }

        $amount     = $vipInfo['amount'];
        $codeId     = 0;
        //优惠码使用
        if($couponCode){
            $codeInfo   = D('Coupon')->useCouponCode($couponCode, $userId, $amount, false);
            if($codeInfo === false){
                $this->errMsg   = D('Coupon')->errMsg;
                return false;
            }
            
            $amount     = $amount - $codeInfo['amount'];
            $codeId     = $codeInfo['id'];
        }

        $remark     = json_encode(['action' => '购买', 'goods_name'   => 'vip_id_'.$vipId]);
        $payInfo    = D('Money')->createPay($userId, 5, $vipId, $amount, $remark, 1, $codeId);
        return $payInfo;
    }
    /**
     * 给予VIP
     * @param   $userId
     * @param   $level  vip等级
     * @param   $timeDesc [时间描述][ +21 day +1 year]
     * @param   $free   是否免费
     * @return  $boolean
     */
    function giveVip($userId, $level, $timeDesc, $free = false){
        $userInfo   = $this->getUserInfo($userId);
        if($userInfo['vip_level'] == 0 || $userInfo['vip_endtime'] < time()){
            $userInfo['vip_endtime']    = time();
        }

        if(!$free && time() < strtotime('2017-09-01') && $userInfo['vip_endtime'] < strtotime('2017-09-01')){
            $userInfo['vip_endtime']    = strtotime('2017-09-01');
        }

        $userInfo['vip_endtime']    = strtotime(date('Y-m-d H:i:s', $userInfo['vip_endtime']).' '.$timeDesc);
        $userInfo['vip_level']  = $level;

        return $this->updateUserInfo($userId, $userInfo);
    }

}
